package com.ruubypay.biz.mvc.workflow.service.impl;

import com.ruubypay.biz.mvc.workflow.model.request.CandidateUser;
import com.ruubypay.biz.mvc.workflow.model.request.ProcessInstanceVO;
import com.ruubypay.biz.mvc.workflow.model.response.AuditProcessResponse;
import com.ruubypay.biz.mvc.workflow.model.response.RuntimeProcessResponse;
import com.ruubypay.biz.activiti.CommonProcessService;
import com.ruubypay.biz.mvc.workflow.service.RuntimeProcessService;
import com.ruubypay.web.common.page.DataGrid;
import com.ruubypay.web.common.utils.StringUtils;
import org.activiti.engine.*;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 运行中的流程实例，接口实现类
 * @author chenhaiyang
 */
@Service("runtimeProcessService")
public class RuntimeProcessServiceImpl extends CommonProcessService implements RuntimeProcessService{

    /**
     * 激活流程的操作标识
     */
    private static final int PROCESS_UNSUSPENDED=1;
    /**
     * 挂起流程的操作标识
     */
    private static final int PROCESS_SUSPENDED=2;

    @Resource
    private ProcessEngine processEngine;

    /**
     * 获取运行中的流程
     * @param paramMap 参数列表
     * @param pageNumber 分页页码
     * @param pageSize pageSize
     * @return 返回流程数据
     */
    @Override
    public DataGrid listDataRuntimeProcesses(Map<String, Object> paramMap, Integer pageNumber, Integer pageSize) {

        ProcessInstanceQuery processInstanceQuery = processEngine.getRuntimeService().createProcessInstanceQuery();

        String name = String.valueOf(paramMap.get("name"));
        if (StringUtils.isNotBlank(name)) {
            processInstanceQuery.processDefinitionName(name);
        }
        String businessKey = String.valueOf(paramMap.get("businessKey"));
        if (StringUtils.isNotBlank(businessKey)) {
            processInstanceQuery.processInstanceBusinessKey(businessKey);
        }

        List<ProcessInstance> processes = processInstanceQuery.listPage((pageNumber-1)*pageSize,pageSize);
        Long count = processInstanceQuery.count();

        List<RuntimeProcessResponse> results =
                Optional.ofNullable(processes)
                        .map(List::stream)
                        .orElseGet(Stream::empty)
                        .map(instance-> buildRuntimeResponseByInstance(instance,processEngine))
                        .collect(Collectors.toList());

        return new DataGrid(count, results);
    }

    /**
     * 挂起/或者激活流程实例
     */
    @Override
    public void suspendedOrNo(ProcessInstanceVO processInstanceVO) {

        if(PROCESS_SUSPENDED==processInstanceVO.getIsSuspended()){
            processEngine.getRuntimeService().suspendProcessInstanceById(processInstanceVO.getProcessInstanceId());
        }
        if(PROCESS_UNSUSPENDED==processInstanceVO.getIsSuspended()){
            processEngine.getRuntimeService().activateProcessInstanceById(processInstanceVO.getProcessInstanceId());
        }
    }

    /**
     * 对历史流程进行作废
     * @param processInstanceVO 流程实例VO类
     */
    @Override
    public void deleteProcessInstance(ProcessInstanceVO processInstanceVO) {
        processEngine.getRuntimeService().deleteProcessInstance(processInstanceVO.getProcessInstanceId(),processInstanceVO.getReason());
    }

    /**
     * 根据任务执行id获取流转历史列表。包括节点信息，审批人，审批历时，批注等信息
     * @param excuseId 流程执行id
     * @return 返回结果
     */
    @Override
    public List<AuditProcessResponse> histoicFlowList(String excuseId) {

        //获取执行对象
        Execution execution = processEngine.getRuntimeService().createExecutionQuery().
                executionId(excuseId).
                singleResult();

        return getHistoicFlowList(processEngine,execution.getProcessInstanceId());
    }

    /**
     * 根据任务的执行Id获取当前整个流程的流程执行情况
     * @param excuseId 执行id
     * @return 返回base64的图片
     */
    @Override
    public String getNowTaskPng(String excuseId) throws IOException {

        Execution execution = processEngine.getRuntimeService().createExecutionQuery().
                executionId(excuseId).
                singleResult();

        return getNowTaskPngByProcessInstanceId(processEngine,execution.getProcessInstanceId());
    }

    /**
     * 根据任务的执行Id重新分配当前任务的办理者
     * @param candidateUser 任务候选人分类对象
     */
    @Override
    public void candidateUser(CandidateUser candidateUser) {

        Task task = processEngine.getTaskService()
                .createTaskQuery()
                .active()
                .executionId(candidateUser.getExcusedId())
                .singleResult();

        processEngine.getTaskService().setAssignee(task.getId(),null);

        String[] users = candidateUser.getUsers().split(",");
        Arrays.stream(users)
                .forEach(user->{
                    processEngine.getTaskService().deleteCandidateUser(task.getId(),user);
                    processEngine.getTaskService().addCandidateUser(task.getId(),user);
                });
    }
}
